package cn.com.sparkle.paxos.stablestorage;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

import com.google.protobuf.ByteString;

import cn.com.sparkle.paxos.deamon.InstanceExecutor;
import cn.com.sparkle.paxos.iomodel.protobuffmessage.PaxosMessages.Id;
import cn.com.sparkle.paxos.iomodel.protobuffmessage.PaxosMessages.InstanceVoteRecord;
import cn.com.sparkle.paxos.iomodel.protobuffmessage.PaxosMessages.SuccessfulRecord;
import cn.com.sparkle.paxos.iomodel.protobuffmessage.PaxosMessages.Value;
//import cn.com.sparkle.paxos.model.Id;
//import cn.com.sparkle.paxos.model.Value;
//import cn.com.sparkle.paxos.stablestorage.model.InstanceVoteRecord;
//import cn.com.sparkle.paxos.stablestorage.model.SuccessfulRecord;
import cn.com.sparkle.paxos.iomodel.protobuffmessage.PaxosMessages.ValueType;
import cn.com.sparkle.paxos.net.callback.PrepareCallBack;
import cn.com.sparkle.paxos.stablestorage.ReadSuccessRecordCallback.SuccessfulRecordWrap;
import cn.com.sparkle.paxos.stablestorage.event.PrepareRecordRealWriteEvent;
import cn.com.sparkle.paxos.stablestorage.model.RecordType;

public class NewTestWritePerformance {
	
	public static void testBatchWrite(int testSize,int valueSize,RecordType type) throws ClassNotFoundException, IOException{
		RecordFileOperator o = new RecordFileOperator(new File("c:/jdpaxos/test1/success"), 0, new InstanceExecutor(null, null, null){
			@Override
			public void execute(SuccessfulRecordWrap record) {
			}
		});
		o.init();
		System.out.println(o.getLastExpectSafeInstanceId());
		System.out.println(o.getVotedInstanceRecordMap().size());
		ByteString bs = ByteString.copyFrom(new byte[valueSize]);
		Value v = Value.newBuilder().setType(ValueType.TYPE_ADMIN).addValues(bs).build();
		Id id = Id.newBuilder().setAddress("").setIncreaseId(0).build();
		long ct = System.currentTimeMillis();
		for (int i = 0; i < testSize; i++) {
			if(type == RecordType.SUCCESS){
				SuccessfulRecord record = SuccessfulRecord.newBuilder().setV(v).build();
				o.writeSuccessfulRecord(i,record,null, null);
			}else{
				InstanceVoteRecord.Builder b = InstanceVoteRecord.newBuilder();
				b.setHighestJoinNum(id).setHighestValue(v).setHighestVotedNum(id);
				InstanceVoteRecord r = b.build();
				o.writeVoteRecord(i, r, null);
			}
		}
		System.out.println(testSize
				/ ((double) (System.currentTimeMillis() - ct) / 1000) + " success/s");
	}
	public static void testWrite(int testSize,int valueSize,RecordType type) throws ClassNotFoundException, IOException, InterruptedException{
		RecordFileOperator o = new RecordFileOperator(new File("c:/jdpaxos/test1/success"), 0, new InstanceExecutor(null, null, null){
			@Override
			public void execute(SuccessfulRecordWrap record) {
			}
		});
		o.init();
		System.out.println(o.getLastExpectSafeInstanceId());
		System.out.println(o.getVotedInstanceRecordMap().size());
		Id id = Id.newBuilder().setAddress("").setIncreaseId(0).build();
		ByteString bs = ByteString.copyFrom(new byte[valueSize]);
		Value v = Value.newBuilder().setType(ValueType.TYPE_ADMIN).addValues(bs).build();
		
		long ct = System.currentTimeMillis();
		for (int i = 0; i < testSize; i++) {
			final CountDownLatch count = new CountDownLatch(1);
			
			if(type == RecordType.SUCCESS){
				Callable<Object> callable = new Callable<Object>() {

					@Override
					public Object call() throws Exception {
						// TODO Auto-generated method stub
						count.countDown();
						return null;
					}
					
				};
				SuccessfulRecord record = SuccessfulRecord.newBuilder().setV(v).build();
				o.writeSuccessfulRecord(i,record,null, callable);
			}else{
				PrepareRecordRealWriteEvent event = new PrepareRecordRealWriteEvent() {
					
					@Override
					public void call(long instanceId,InstanceVoteRecord record) {
						count.countDown();
						
					}
				};
				InstanceVoteRecord.Builder b = InstanceVoteRecord.newBuilder();
				b.setHighestJoinNum(id).setHighestValue(v).setHighestVotedNum(id);
				InstanceVoteRecord r = b.build();
				o.writeVoteRecord(i, r, event);
			}
			count.await();
		}
		System.out.println(testSize
				/ ((double) (System.currentTimeMillis() - ct) / 1000) + " success/s");
		
		
	}
	
	public static void main(String[] args) {
		Thread t1 = new Thread(){
			public void run(){
				try {
					testWrite(1,1024,RecordType.VOTE);
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} 
			}
		};
		Thread t2 = new Thread(){
			public void run(){
				try {
//					testBatchWrite(10000,1024,RecordType.SUCCESS);
					testWrite(1,1024,RecordType.SUCCESS);
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} 
				/*catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}*/
			}
		};
		t1.start();
		t2.start();
		
	}
}
